﻿/*
 * jqGrid Dataview v0.2.0
 *
 * Implementation of generating jqGrid style requests
 * Copyright © 2012 Tomasz Pęczek
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 * Depends on:
 * - jquery.ui.widget.js
 * - jquery.ui.observable.js
 * - jquery.ui.dataview.js
 */
(function ($, undefined) {
    $.widget("ui.jqGridDataview", $.ui.dataview, {
        widgetEventPrefix: "dataview",
        options: {
            methodType: "GET",
            parametersNames: {
                page: "page",
                rows: "rows",
                sort: "sidx",
                order: "sord",
                search:"_search",
                filter: "filters",
                nd: "nd"
            },
            paging: {
                limit: 20
            },
            resource: null,
            ajaxOptions: {},
            stringResult: false,
            groupOp: "AND",
            postData: {},
            beforeRequest: null,
            serializeGridData: null,
            beforeProcessing: null,
            loadBeforeSend: null,
            loadComplete: null,
            loadError: null,
            source: function (request, response) {
                var data = { };
                data[request.parametersNames.nd] = new Date().getTime();
                data[request.parametersNames.rows] = request.paging.limit;
                data[request.parametersNames.page] = (request.paging.offset / request.paging.limit) + 1;

                if (request.sort.length === 1) {
                    if (request.sort[0].slice(0, 1) === "-") {
                        data[request.parametersNames.sort] = request.sort[0].slice(1);
                        data[request.parametersNames.order] = "desc";
                    } else {
                        data[request.parametersNames.sort] = request.sort[0];
                        data[request.parametersNames.order] = "asc";
                    }
                }

                if (request.filter) {
                    data[request.parametersNames.search] = true;

                    if (request.stringResult === true) {
                        var filters = { groupOp: request.groupOp, rules: [] };
                        $.each(request.filter, function (property, filter) {
                            if (!filter.operator) {
                                filter.operator = isNaN(filter.value) ? "like" : "==";
                            }

                            var operators = {
                                "<": "lt",
                                "<=": "le",
                                ">": "gt",
                                ">=": "ge",
                                "==": "eq",
                                "!=": "ne",
                                "like": "bw"
                            };

                            filter.value += "";
                            filters.rules.push({ field: property, op: operators[filter.operator], data: filter.value.replace(/\\/g, '\\\\').replace(/\"/g, '\\"') }); //= "{\"field\":\"" + property + "\",\"op\":\"" + operators[filter.operator] + "\",\"data\":\"" + filter.value.replace(/\\/g, '\\\\').replace(/\"/g, '\\"') + "\"}";
                        });
                        data[request.parametersNames.filter] = JSON.stringify(filters);
                    } else {
                        var filters = [];
                        $.each(request.filter, function (property, filter) {
                            filters[property] = filter.value;
                        });
                        $.extend(data, filters);
                    }
                } else {
                    data[request.parametersNames.search] = false;
                }

                if($.isFunction(request.beforeRequest)) {
                    beforeRequestResult = request.beforeRequest.call(this);
                    if(beforeRequestResult === undefined) {
                        beforeRequestResult = true;
                    }
                    if (beforeRequestResult === false) {
                        return;
                    }
                }

                var ts = this;
                var postData = request.postData;
                $.extend(postData, data);

                $.ajax($.extend({
                    url: request.resource,
                    type: request.methodType,
                    dataType: "json",
                    data: $.isFunction(request.serializeGridData) ? request.serializeGridData.call(ts, postData) : postData,
                    success: function(data, textStatus, jqXHR) {
                        if ($.isFunction(request.beforeProcessing)) {
                            if (request.beforeProcessing.call(ts, data, textStatus, jqXHR) === false) {
                                return;
                            }
                        }

                        response(data.rows, data.records);

                        if($.isFunction(request.loadComplete)) {
                            request.loadComplete.call(ts, data);
                        }

                        data = null;
                    },
                    error: function(jqXHR, textStatus, errorThrown) {
                        if($.isFunction(request.loadError)) {
                            request.loadError.call(ts, jqXHR, textStatus, errorThrown);
                        }

                        jqXHR = null;
                    },
                    beforeSend: function(jqXHR, settings) {
                        var loadBeforeSendResult = true;
                        if($.isFunction(request.loadBeforeSend)) {
                            loadBeforeSendResult = request.loadBeforeSend.call(ts, jqXHR, settings); 
                        }
                        if(loadBeforeSendResult === undefined) {
                            loadBeforeSendResult = true;
                        }
                        if(loadBeforeSendResult === false) {
                            return false;
                        }
                    }
                }, request.ajaxOptions));
            }
        }
    });
} (jQuery));
